/*
 * test_comtrade.cpp
 *
 *  Created on: 2019年11月20日
 *      Author: turne
 */

#include <dm/app/comtradereader.hpp>
#include <dm/app/comtradewriter.hpp>

#include <boost/program_options.hpp>
#include <iostream>
#include <cmath>
#include <dm/datetime.hpp>

using namespace std;
using namespace boost::program_options;

int main( int argc,char* argv[] ){
	options_description desc("DM测试COMTRADE库工具");
	desc.add_options()
			("help,h","显示本帮助信息")
			("version,v","显示版本及编译信息")
			("name",value<string>(),"录波文件名。参数为录波文件名,不含路径及扩展名部分")
			("write",value<string>(),"是否产生录波文件。参数可以是BINARY 或者 ASCII。不指定则表示读取")
			("measures",value<int>()->default_value(10),"测量量数量")
			("status",value<int>()->default_value(4),"状态量数量")
			;

	variables_map vm;
	try{
		store(parse_command_line(argc,argv,desc),vm);
		notify(vm);
	}catch( std::exception& ex ){
		cout << ex.what()<<endl;
		return 1;
	}

	if( vm.count("version") ){
		cout <<"V1.0 构建于 "<<__DATE__<<endl;
		return 1;
	}

	if( vm.count("help") ){
		cout <<desc<<endl;
		return 1;
	}

	if( !vm.count("name") ){
		cout <<"请使用选项--name指定文件名"<<endl;
		return 1;
	}

	if( vm.count("write") ){
		// 写文件
		dm::app::CComtradeWriter writer;
		writer.setName(vm["name"].as<string>().c_str());

		if( vm["write"].as<string>()=="BINARY" || vm["write"].as<string>()=="binary" )
			writer.setFt(dm::app::CComtradeWriter::FormatBinary);
		else if( vm["write"].as<string>()=="ASCII" || vm["write"].as<string>()=="ascii" )
			writer.setFt(dm::app::CComtradeWriter::FormatAscii);
		else{
			cout <<"选项--write参数"<<vm["write"].as<string>()<<"错误"<<endl;
			return 1;
		}

		writer.setNetFreq(50.00);
		writer.setStationName("测试站");
		writer.setTsStart(dm::CTimeStamp::cur());

		writer.addRate(dm::app::CComtradeWriter::CRate(500.0,1024));

		int measureCount = vm["measures"].as<int>();
		for( int i=0;i<measureCount;++i ){
			dm::app::CComtradeWriter::CMeasureInfo m;

			m.setChId("AD");
			m.setUu("V");
			m.setCcbm("测试单元");
			m.setSkew(0);
			m.setMin(-1000);
			m.setMax(1000);
			writer.addMeasureInfo(m);
		}

		int statusCount = vm["status"].as<int>();
		for( int i=0;i<statusCount;++i ){
			dm::app::CComtradeWriter::CStatusInfo s;

			s.setChId("DI");
			s.setCcbm("测试单元");

			writer.addStatusInfo(s);
		}

		dm::CTimeStamp n = dm::CTimeStamp::cur();
		n.addSec(1);
		writer.setTsTrig(n);

		if( !writer.dump() ){
			cout <<"生成COMTRADE文件"<<vm["name"].as<string>()<<"失败"<<endl;
			return 1;
		}

		dm::app::CComtradeWriter::measure_t* m = NULL;
		dm::app::CComtradeWriter::status_t* s = NULL;

		if( measureCount>0 )
			m = new dm::app::CComtradeWriter::measure_t[measureCount];
		if( statusCount>0 )
			s = new dm::app::CComtradeWriter::status_t[statusCount];

		for( int i=0;i<1024;++i ){
			for( int j=0;j<measureCount;++j ){
				m[j] = 1000*sin(3.14*4/1024*i+j*2);
			}

			for( int j=0;j<statusCount;++j )
				s[j] = ((i+j)%2);

			if( !writer.append(m,measureCount,s,statusCount,NULL) ){
				cout <<"导出数据失败"<<i<<endl;
				return 1;
			}
		}

		cout <<"生成COMTRADE文件"<<vm["name"].as<string>()<<"成功"<<endl;
		return 0;
	}else{
		// 读取文件
		dm::app::CComtradeReader reader;

		reader.setName(vm["name"].as<string>().c_str());
		if( !reader.load() ){
			cout <<"加载COMTRADE文件"<<vm["name"].as<string>()<<"失败"<<endl;
			return 1;
		}

		cout <<"场站名:";
		if( reader.stationName() )
			cout <<reader.stationName();
		cout <<" 标识:";
		if( reader.recDevId() )
			cout<<reader.recDevId();
		cout <<" 版本年号:"<<reader.revYear()<<endl;

		cout <<"测量量数:"<<reader.measureCount()<<endl;
		for( unsigned int i=0;i<reader.measureCount();++i ){
			const dm::app::CComtradeReader::CMeasureInfo& m = reader.measure(i);
			cout <<i+1<<" 通道标识:";
			if( m.chId() )
				cout <<m.chId();
			cout <<" 相别:";
			if( m.ph() )
				cout <<m.ph();
			cout <<" 电路元件:";
			if( m.ccbm() )
				cout <<m.ccbm();

			cout <<" 通道单位:";
			if( m.uu() )
				cout <<m.uu();

			cout <<" 通道倍率:"<<m.a()<<" 偏移:"<<m.b()<<" 时滞:"<<m.skew()<<" 最小值:"<<m.min()<<" 最大值:"<<m.max()
					<<" 变比:"<<m.primary()<<":"<<m.secondary()<<" PS:"<<m.ps()<<endl;
		}

		cout <<"状态量数:"<<reader.statusCount()<<endl;
		for( unsigned int i=0;i<reader.statusCount();++i ){
			const dm::app::CComtradeReader::CStatusInfo& s = reader.status(i);
			cout <<i+1<<" 通道标识:";
			if( s.chId() )
				cout <<s.chId();
			cout <<" 相别:";
			if( s.ph() )
				cout <<s.ph();
			cout <<" 电路元件:";
			if( s.ccbm() )
				cout <<s.ccbm();

			cout <<" 正常状态:"<<s.y()<<endl;
		}

		cout <<"电网频率:"<<reader.netFreq()<<endl;

		cout <<"采样速率数:"<<reader.ratesCount()<<endl;
		for( unsigned int i=0;i<reader.ratesCount();++i ){
			const dm::app::CComtradeReader::CRate& r = reader.rate(i);
			cout <<"采样频率:"<<r.samp()<<" 最后采样点:"<<r.endSamp()<<endl;
		}

		cout <<"开始采样时标:"<<dm::CDateTime(reader.tsStart()).toString()<<endl;
		cout <<"触发时刻:"<<dm::CDateTime(reader.tsTrig()).toString()<<endl;

		cout <<"数据文件格式:";
		if( reader.ft()==dm::app::CComtradeReader::FormatBinary )
			cout <<"二进制";
		else if( reader.ft()==dm::app::CComtradeReader::FormatAscii )
			cout <<"ASCII";
		else
			cout <<"未知";

		cout <<"\n时标倍率因子:"<<reader.timeMult()<<endl;

		int rowCount = reader.rows();
		cout <<"\n数据记录:"<<rowCount<<endl;

		unsigned int mc = reader.measureCount();
		unsigned int sc = reader.statusCount();

		dm::app::CComtradeReader::measure_t* ms = NULL;
		dm::app::CComtradeReader::status_t* ss = NULL;
		dm::CTimeStamp ts;

		if( mc>0 )
			ms = new dm::app::CComtradeReader::measure_t[mc];
		if( ss>0 )
			ss = new dm::app::CComtradeReader::status_t[sc];

		for( int i=0;i<rowCount;++i ){
			if( !reader.getNext(ms,mc,ss,sc,&ts) ){
				cout <<"读取记录"<<i<<"失败"<<endl;
				return 1;
			}

			cout <<"记录"<<i<<" "<<dm::CDateTime(ts).toString();
			if( mc>0 ){
				cout <<" 测量量:";
				for( unsigned int j=0;j<mc;++j )
					cout <<ms[j]<<',';
			}

			if( sc>0 ){
				cout <<" 状态量:";
				for( unsigned int j=0;j<sc;++j )
					cout <<ss[j]<<',';
			}

			cout <<endl;
		}
	}

	return 0;
}
